#ifndef LAURIN_DEVICE_H_
#define LAURIN_DEVICE_H_

#include <pcap.h>
#include <glibmm/ustring.h>

/**
 * This class is central for the Laurin Project.
 *
 * It try to represent a network device in a generic manner (every 802.XX device is supported).
 * It offers basic functionalities like:
 *
 *
 * 1) set device up/down
 * 2) get mac address
 * 3) get device index
 * 4) get device name
 *
 * It also offers packet capture functionalities through the pcap API.
 * Before use this functionality we need to acquire a pcap_t* context through getCaptureContext().
 */
class LaurinDevice
{
	public:


		LaurinDevice(const Glib::ustring& ifaceName);
		virtual ~LaurinDevice();

		bool setDeviceUp();
		bool setDeviceDown();
		bool isDeviceUp();

		/**
		 * Acquire pcap context. If some error occurs, false is returned.
		 */
		bool openCaptureContext();

		/**
		 * Add filter to the capture context.
		 */
		bool setCaptureFilter(const Glib::ustring& filterSTM, int subnetMask);


		/**
		 * Return the capture context. NULL if no opened.
		 */
		pcap_t* getCaptureContext() const;

		/**
		 * Must be called before use the object.
		 * It return true only if device is correctly initialized.
		 * False otherwise.
		 */
		virtual bool isInitialized() const;


		/**
		 * Return the datalink layer code.
		 * It return a valid code only if the capture context is initialized.
		 */
		int getDataLayerLink() const;
		int getDeviceIndex() const;
		u_int8_t* getMAC() const;
		Glib::ustring getDeviceName() const;
		Glib::ustring getErrorMessage() const;


	protected:

		/**
		 * Acquire the mac address
		 */
		bool retrieveMACAddress();

		/**
		 * Set specific capture options.
		 * This is called on getCaptureContext()
		 */
		virtual bool setCaptureOptions();


		u_int8_t* _mac;
		pcap_t* _capture_context;
		Glib::ustring _ifaceName;
		Glib::ustring _errmess;
		int _ifaceIndex;


	private:

		/*
		 * Set device up/down status. If flag is true then up, otherwise down.
		 */
		bool setDeviceStatus(short flag);
		void closeCaptureContext();


		bool _initialized;
		int _datalayer;

};

#endif
